#include "../StdInc.h"
#include "iomanip"
#include "time.h"
#include <boost/date_time/local_time_adjustor.hpp>
#include <boost/date_time/c_local_time_adjustor.hpp>

namespace GSTrader
{
	namespace Util
	{
		CLTimeSpan::CLTimeSpan()
		{

		}

		CLTimeSpan::~CLTimeSpan()
		{
		}

#ifndef maxTimeBufferSize
	#define maxTimeBufferSize 128
#endif
#ifndef _countof
	#define _countof(array) (sizeof(array)/sizeof(array[0]))
#endif
		CTTime::CTTime()
		{
			m_time = 0;
		}

		CTTime::CTTime(time_t tTime)
		{
			m_time = tTime;
		}

		CTTime::~CTTime()
		{

		}

		CTTime::CTTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, int nDST)
		{
			struct tm atm;
			atm.tm_sec = nSec;
			atm.tm_min = nMin;
			atm.tm_hour = nHour;
			assert(nDay >= 1 && nDay <= 31);
			atm.tm_mday = nDay;
			assert(nMonth >= 1 && nMonth <= 12);
			atm.tm_mon = nMonth - 1;
			assert(nYear >= 1900);
			atm.tm_year = nYear - 1900;
			atm.tm_isdst = nDST;
			m_time = mktime(&atm);
			assert(m_time != -1);
		}

		CTTime::CTTime(const CTTime& timeSrc)
		{
			m_time = timeSrc.m_time;
		}

		time_t CTTime::GetTimeBeginDay(time_t t)
		{
			struct tm* pt;
			pt = localtime(&t);
			pt->tm_hour = 0;
			pt->tm_min = 0;
			pt->tm_sec = 0;

			return mktime(pt);
		}

		CTTime CTTime::GetCurTime()
		{
			return CTTime(::time(NULL));
		}

		tm* CTTime::GetLocalTm(tm* ptm) const
		{
			if (ptm != NULL)
			{
				struct tm* ptmTemp = localtime(&m_time);
				if (ptmTemp == NULL)
				{
					return NULL;
				}

				*ptm = *ptmTemp;
				return ptm;
			}
			else
			{
				return localtime(&m_time);
			}
		}

		string CTTime::Format(char* pFormat)
		{
			char szBuffer[maxTimeBufferSize];
			struct tm* ptmTemp = localtime(&m_time);
			if (ptmTemp == NULL || !strftime(szBuffer, sizeof(szBuffer), pFormat, ptmTemp))
			{
				szBuffer[0] = '\0';
			}

			return szBuffer;
		}

		const CTTime& CTTime::operator = (const CTTime& timeSrc)
		{
			m_time = timeSrc.m_time;
			return *this;
		}

		const CTTime& CTTime::operator = (const time_t& timeSrc)
		{
			m_time = timeSrc;
			return *this;
		}

		bool CTTime::operator == (CTTime time) const
		{
			return m_time == time.m_time;
		}

		bool CTTime::operator != (CTTime time) const
		{
			return m_time != time.m_time;
		}

		bool CTTime::operator < (CTTime time) const
		{
			return m_time < time.m_time;
		}

		bool CTTime::operator >(CTTime time) const
		{
			return m_time > time.m_time;
		}

		bool CTTime::operator <= (CTTime time) const
		{
			return m_time <= time.m_time;
		}

		bool CTTime::operator >= (CTTime time) const
		{
			return m_time >= time.m_time;
		}

		time_t CTTime::GetTime() const
		{
			return m_time;
		}

		int CTTime::GetYear() const
		{
			tm* pTm = GetLocalTm(NULL);
			if (pTm)
			{
				return (pTm->tm_year) + 1900;
			}
			
			return 0;
		}

		int CTTime::GetMonth() const
		{
			tm* pTm = GetLocalTm(NULL);
			if (pTm)
			{
				return pTm->tm_mon + 1;
			}

			return 0;
		}

		int CTTime::GetDay() const
		{
			tm* pTm = GetLocalTm(NULL);
			if (pTm)
			{
				return pTm->tm_mday;
			}
			
			return 0;
		}

		int CTTime::GetHour() const
		{
			tm* pTm = GetLocalTm(NULL);
			if (pTm)
			{
				return pTm->tm_hour;
			}

			return 0;
		}

		int CTTime::GetMinute() const
		{
			tm* pTm = GetLocalTm(NULL);
			if (pTm)
			{
				return pTm->tm_min;
			}

			return 0;
		}

		int CTTime::GetSecond() const
		{
			tm* pTm = GetLocalTm(NULL);
			if (pTm)
			{
				return pTm->tm_sec;
			}

			return 0;
		}

		int CTTime::GetDayOfWeek() const
		{
			tm* pTm = GetLocalTm(NULL);
			if (pTm)
			{
				return pTm->tm_wday + 1;
			}

			return 0;
		}

		time_t CTTime::operator +(time_t time)
		{
			m_time += time;
			return m_time;
		}

		CTimePoint::CTimePoint()
		{
			m_time = system_clock::now();
		}

		CTimePoint::CTimePoint(system_clock::time_point _time)
		{
			m_time = _time;
		}

		CTimePoint::CTimePoint(const CTimePoint& _hptime)
		{
			m_time = _hptime.m_time;
		}

		CTimePoint::CTimePoint(const time_t& _time)
		{
			m_time = system_clock::from_time_t(_time);
		}

		CTimePoint::CTimePoint(int nYears, int nMonth, int nDay, int nHour, int nMin, int nSecond, int nIsDst)
		{
			tm t_tm;
			t_tm.tm_year = nYears - 1990;
			t_tm.tm_mon = nMonth;
			t_tm.tm_mday;
			t_tm.tm_hour = nHour;
			t_tm.tm_min = nMin;
			t_tm.tm_sec = nSecond;
			t_tm.tm_isdst = nIsDst;
			time_t ttime = mktime(&t_tm);
			m_time = system_clock::from_time_t(ttime);
		}

		double CTimePoint::GetTicks(Ticks& _ticks)
		{
			return _ticks.count();
		}

		void CTimePoint::SetTime(time_t t, int nMilliSecond)
		{
			//	typedef duration <Rep, ratio<1, 1000>> milliseconds;
			milliseconds m1(nMilliSecond);
			m_time = system_clock::from_time_t(t);
			m_time += m1;
		}

		void CTimePoint::AddSecond(int nSecond)
		{
			seconds s1(nSecond);
			m_time += s1;
		}

		void CTimePoint::AddMilliSecond(int nMilliSecond)
		{
			milliseconds s1(nMilliSecond);
			m_time += s1;
		}

		Ticks CTimePoint::Subtract(const CTimePoint& _hpTime)
		{
			return (m_time - _hpTime.m_time);
		}

		CTimePoint CTimePoint::GetTimeBeginDay(CTimePoint& t)
		{
			time_t t1 = t.GetTime_t();
			time_t tBegin = CTTime::GetTimeBeginDay(t1);
			CTimePoint tpBegin = system_clock::from_time_t(tBegin);

			return tpBegin;
		}

		bool CTimePoint::operator == (const CTimePoint& _hpTime)
		{
			if (_hpTime.m_time == m_time)
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		bool CTimePoint::operator != (const CTimePoint& _hpTime)
		{
			if (_hpTime.m_time != m_time)
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		bool CTimePoint::operator < (const CTimePoint& _hpTime)
		{
			if (m_time < _hpTime.m_time)
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		int CTimePoint::operator - (const CTimePoint& _hpTime)
		{
			Ticks t = Subtract(_hpTime);
			return (int)(GetTicks(t) / 10000000);
		}

		bool CTimePoint::operator >(const CTimePoint& _hpTime)
		{
			if (m_time > _hpTime.m_time)
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		bool CTimePoint::operator <= (const CTimePoint& _hpTime)
		{
			if (m_time <= _hpTime.m_time)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		bool CTimePoint::operator >= (const CTimePoint& _hpTime)
		{
			if (m_time >= _hpTime.m_time)
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		const system_clock::time_point& CTimePoint::GetTime()
		{
			return m_time;
		}

		time_t CTimePoint::GetTime_t()
		{
			return system_clock::to_time_t(m_time);
		}

		string CTimePoint::ToString()
		{
			string strFmt;
			ToString(strFmt, 0);
			return strFmt;
		}

		string CTimePoint::Format(string strFmt)
		{
#ifdef  _RUN_WINDOWS_
			tm* _tmtime;
			time_t _ttime = system_clock::to_time_t(m_time);
			_tmtime = localtime(&_ttime);

			stringstream sstream;
			sstream << put_time(_tmtime, strFmt.c_str());

			string strTime;
			sstream >> strTime;
			return strTime;
#endif

			return "";
		}

		void CTimePoint::ToString(string& TimeFormat, int prec)
		{
			long long timeprec = 0;
			tm* _tmtime;
			time_t _ttime = system_clock::to_time_t(m_time);
			_tmtime = localtime(&_ttime);

			stringstream sstream;
			if (prec == 0)
			{
				sstream << (_tmtime->tm_year + 1900) << "-" << _tmtime->tm_mon + 1 << "-" << _tmtime->tm_mday << "|" << _tmtime->tm_hour << ":" << _tmtime->tm_min <<
				        ":" << _tmtime->tm_sec;
				sstream >> TimeFormat;
			}
			else if (prec == 1)
			{
				time_point<system_clock, std::chrono::seconds> second = time_point_cast<std::chrono::seconds>(m_time);
				time_point<system_clock, std::chrono::milliseconds> ms = time_point_cast<std::chrono::milliseconds>(m_time);
				timeprec = (ms.time_since_epoch().count()) - (second.time_since_epoch().count() * 1000);
				sstream << (_tmtime->tm_year + 1900) << "-" << _tmtime->tm_mon + 1 << "-" << _tmtime->tm_mday << "|" << _tmtime->tm_hour << ":" << _tmtime->tm_min <<
				        ":" << _tmtime->tm_sec << "." << timeprec << "ms";
				sstream >> TimeFormat;
			}
			else if (prec == 2)
			{
				time_point<system_clock, std::chrono::milliseconds> ms = time_point_cast<std::chrono::seconds>(m_time);
				time_point<system_clock, std::chrono::microseconds> mms = time_point_cast<std::chrono::milliseconds>(m_time);
				timeprec = (mms.time_since_epoch().count()) - (ms.time_since_epoch().count() * 1000);
				sstream << (_tmtime->tm_year + 1900) << "-" << _tmtime->tm_mon + 1 << "-" << _tmtime->tm_mday << "|" << _tmtime->tm_hour << ":" << _tmtime->tm_min <<
				        ":" << _tmtime->tm_sec << "." << timeprec << "mms";
				sstream >> TimeFormat;
			}
			else if (prec == 3)
			{
				time_point<system_clock, std::chrono::microseconds> mms = time_point_cast<std::chrono::seconds>(m_time);
				time_point<system_clock, std::chrono::nanoseconds> ns = time_point_cast<std::chrono::milliseconds>(m_time);
				timeprec = (ns.time_since_epoch().count()) - (mms.time_since_epoch().count() * 1000);
				sstream << (_tmtime->tm_year + 1900) << "-" << _tmtime->tm_mon + 1 << "-" << _tmtime->tm_mday << "|" << _tmtime->tm_hour << ":" << _tmtime->tm_min <<
				        ":" << _tmtime->tm_sec << "." << timeprec << "ns";
				sstream >> TimeFormat;
			}
		}

		CTimePoint CTimePoint::Now()
		{
			CTimePoint _time;
			_time.m_time = system_clock::now();
			return _time;
		}

		CTimePoint::~CTimePoint()
		{

		}

		CTimePoint& CTimePoint::operator = (const CTimePoint& _hpTime)
		{
			if (this == (&_hpTime))
			{
				return (*this);
			}
			m_time = _hpTime.m_time;
			return *this;
		}

		CTimePoint& CTimePoint::operator = (const time_t& _ttime)
		{
			m_time = system_clock::from_time_t(_ttime);
			return (*this);
		}
	}
}